#ifndef ENDIANNES_H
#define ENDIANNES_H

#include <byteswap.h>
#include <fstream>


namespace smf {
inline void swap(unsigned short& x)
{
    x = (x>>8) |
        (x<<8);
}

inline void swap(unsigned int& x)
{
x =__builtin_bswap32 (x);
}

inline void swap(unsigned long& x)
{
x =__builtin_bswap32 (x);
}

// __int64 for MSVC, "long long" for gcc
inline void swap(unsigned long long& x)
{
x =__builtin_bswap64 (x);
}

inline void read(std::fstream* file, unsigned char &c){
    char *temp = reinterpret_cast<char *>(&c);
    file->read(temp, 1);
}

inline void read(std::fstream* file, unsigned short& us){
    union { char c[sizeof(us)]; unsigned short s;} temp;
    file->read(temp.c, sizeof(us));
    swap(temp.s);
    us = temp.s;
}

inline void read(std::fstream* file, unsigned int& ul){
    union { char c[sizeof(ul)]; unsigned int s;} temp;
    file->read(temp.c, sizeof(ul));
    swap(temp.s);
    ul = temp.s;
}

inline void read(std::fstream* file, unsigned long& ul){
    union { char c[sizeof(ul)]; unsigned long s;} temp;
    file->read(temp.c, sizeof(ul));
    swap(temp.s);
    ul = temp.s;
}

inline void read(std::fstream* file, unsigned long long& ull){
    union { char c[sizeof(ull)]; unsigned long long s;} temp;
    file->read(temp.c, sizeof(ull));
    swap(temp.s);
    ull = temp.s;
}

inline void read(std::fstream* file, unsigned char *uc, size_t size){
    char *c = reinterpret_cast<char *>(uc);
    file->read(c, size);
}

inline int readDelta(std::fstream* file, unsigned long long& x){
    int i = 0;
    x = 0;
    for (i = 0; i<4 ; ++i){
        char c; file->read(&c, 1);
        x |= c & 0x7f;
        if ((c & 0x80) == 0) return x+1;
        x<<7;
    }
    return 0;
}
}

#endif // ENDIANNES_H


